#include "tlmbms_protocol.h"

// read-only registers
#define REG0000_007C_SIZE (125)
#define REG007D_00F9_SIZE (125)
#define REG00FA_0176_SIZE (125)
#define REG0177_01F3_SIZE (125)
#define REG01F4_021B_SIZE (40)

#define REG05F4_065F_SIZE (108)

#define REG03E8_03F1_SIZE (10)
#define REG0484_0485_SIZE (2)
#define REG047D_SIZE (1)

// read-write registers
//...

// read-only registers
static uint16_t reg0000_007C[REG0000_007C_SIZE];
static uint16_t reg007D_00F9[REG007D_00F9_SIZE];
static uint16_t reg00FA_0176[REG00FA_0176_SIZE];
static uint16_t reg0177_01F3[REG0177_01F3_SIZE];
static uint16_t reg01F4_021B[REG01F4_021B_SIZE];
static uint16_t reg05F4_065F[REG05F4_065F_SIZE];
static uint16_t reg03E8_03F1[REG03E8_03F1_SIZE];
static uint16_t reg0484_0485[REG0484_0485_SIZE];
static uint16_t reg047D[REG047D_SIZE];

// n->[1,27]，m->[0,11]，这里为十进制，n为电池包，m为电池
uint16_t *get_bms_n_cell_m_0_0001V(uint8_t n, uint8_t m)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        if (0 <= m && m <= 7)
        { // 0x0000-0x01AF
            addr = (n - 1) * 16 + m;
            if (0x0000 <= addr && addr <= 0x007C)
            {
                res = reg0000_007C + (addr - 0x0000);
            }
            else if (0x007D <= addr && addr <= 0x00F9)
            {
                res = reg007D_00F9 + (addr - 0x007D);
            }
            else if (0x00FA <= addr && addr <= 0x0176)
            {
                res = reg00FA_0176 + (addr - 0x00FA);
            }
            else if (0x0177 <= addr && addr <= 0x01F3)
            {
                res = reg0177_01F3 + (addr - 0x0177);
            }
        }
        if (8 <= m && m <= 11)
        { // 0x01B0-0x021B
            addr = (n - 1) * 4 + (m - 8) + 432;
            if (0x0177 <= addr && addr <= 0x01F3)
            {
                res = reg0177_01F3 + (addr - 0x0177);
            }
            else if (0x01F4 <= addr && addr <= 0x021B)
            {
                res = reg01F4_021B + (addr - 0x01F4);
            }
        }
    }
    return res;
}

// n->[1,27]，m->[0,7]，这里为十进制
int16_t *get_bms_n_cell_m_0_1T(uint8_t n, uint8_t m)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        if (0 <= m && m <= 7)
        { // 0x0000-0x01AF
            addr = (n - 1) * 16 + m + 8;
            if (0x0000 <= addr && addr <= 0x007C)
            {
                res = reg0000_007C + (addr - 0x0000);
            }
            else if (0x007D <= addr && addr <= 0x00F9)
            {
                res = reg007D_00F9 + (addr - 0x007D);
            }
            else if (0x00FA <= addr && addr <= 0x0176)
            {
                res = reg00FA_0176 + (addr - 0x00FA);
            }
            else if (0x0177 <= addr && addr <= 0x01F3)
            {
                res = reg0177_01F3 + (addr - 0x0177);
            }
        }
    }
    return (int16_t *)res;
}

// n->[1,27]，这里为十进制，n为电池包
uint16_t *get_bms_n_cell_max_0_0001V(uint8_t n)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        addr = (n - 1) * 4 + 1524 + 0;
        res = reg05F4_065F + (addr - 0x05F4);
    }
    return res;
}

// n->[1,27]，这里为十进制，n为电池包
uint16_t *get_bms_n_cell_m_min_0_0001V(uint8_t n)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        addr = (n - 1) * 4 + 1524 + 1;
        res = reg05F4_065F + (addr - 0x05F4);
    }
    return res;
}

// n->[1,27]，这里为十进制，n为电池包
int16_t *get_bms_n_cell_m_max_0_1T(uint8_t n)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        addr = (n - 1) * 4 + 1524 + 2;
        res = reg05F4_065F + (addr - 0x05F4);
    }
    return (int16_t *)res;
}

// n->[1,27]，这里为十进制，n为电池包
int16_t *get_bms_n_cell_m_min_0_1T(uint8_t n)
{
    uint16_t *res = NULL;
    if (1 <= n && n <= 27)
    {
        uint16_t addr;
        addr = (n - 1) * 4 + 1524 + 3;
        res = reg05F4_065F + (addr - 0x05F4);
    }
    return (int16_t *)res;
}

uint16_t *get_bms_total_0_1V_1()
{
    return reg03E8_03F1;
}

int16_t *get_bms_total_0_1A_1()
{
    return (int16_t *)(reg03E8_03F1 + 1);
}

uint16_t *get_bms_SOC()
{
    return reg03E8_03F1 + 2;
}

bms_fault_code_1_t *get_bms_Fault_Code_1()
{
    return (bms_fault_code_1_t *)(reg03E8_03F1 + 3);
}

bms_fault_code_2_t *get_bms_Fault_Code_2()
{
    return (bms_fault_code_2_t *)(reg03E8_03F1 + 4);
}

bms_fault_code_3_t *get_bms_Fault_Code_3()
{
    return (bms_fault_code_3_t *)(reg03E8_03F1 + 5);
}

uint16_t *get_bms_max_0_0001V()
{
    return reg03E8_03F1 + 6;
}

uint16_t *get_bms_min_0_0001V()
{
    return reg03E8_03F1 + 7;
}

int16_t *get_bms_max_0_1T()
{
    return (int16_t *)reg03E8_03F1 + 8;
}

int16_t *get_bms_min_0_1T()
{
    return (int16_t *)reg03E8_03F1 + 9;
}

uint16_t *get_bms_total_0_1V_2()
{
    return reg0484_0485;
}

int16_t *get_bms_total_0_1A_2()
{
    return (int16_t *)(reg0484_0485 + 1);
}

bms_statu_t *get_bms_status()
{
    return (bms_statu_t *)reg047D;
}

// REG read functions
uint8_t tlmbms_RO_regs_read(modbusHandler_t *modH)
{
    static uint8_t statecode = 0;
    if (statecode >= 9)
        statecode = 0;
    switch (statecode)
    {
    case 0:
        // if (bmsreg0000_007C_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 1:
        // if (bmsreg007D_00F9_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 2:
        // if (bmsreg00FA_0176_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 3:
        // if (bmsreg0177_01F3_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 4:
        // if (bmsreg01F4_021B_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 5:
        // if (bmsreg05F4_065F_read(modH))
        // {
            statecode++;
        // }
        // else
        //     break;
    case 6:
        if (bmsreg03E8_03F1_read(modH))
        {
            statecode++;
        }
        else
            break;
    case 7:
        if (bmsreg0484_0485_read(modH))
        {
            statecode++;
        }
        else
            break;
    case 8:
        if (bmsreg047D_read(modH))
        {
            statecode++;
        }
        else
            break;
    default:
        break;
    }
    return statecode;
}

bool bmsreg0000_007C_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x0000;
    frame.u16CoilsNo = REG0000_007C_SIZE;
    frame.u16reg = reg0000_007C;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg007D_00F9_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x007D;
    frame.u16CoilsNo = REG007D_00F9_SIZE;
    frame.u16reg = reg007D_00F9;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg00FA_0176_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x00FA;
    frame.u16CoilsNo = REG00FA_0176_SIZE;
    frame.u16reg = reg00FA_0176;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg0177_01F3_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x0177;
    frame.u16CoilsNo = REG0177_01F3_SIZE;
    frame.u16reg = reg0177_01F3;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg01F4_021B_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x01F4;
    frame.u16CoilsNo = REG01F4_021B_SIZE;
    frame.u16reg = reg01F4_021B;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg05F4_065F_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x05F4;
    frame.u16CoilsNo = REG05F4_065F_SIZE;
    frame.u16reg = reg05F4_065F;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg03E8_03F1_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x03E8;
    frame.u16CoilsNo = REG03E8_03F1_SIZE;
    frame.u16reg = reg03E8_03F1;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg0484_0485_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x0484;
    frame.u16CoilsNo = REG0484_0485_SIZE;
    frame.u16reg = reg0484_0485;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}

bool bmsreg047D_read(modbusHandler_t *modH)
{
    modbus_t frame;
    frame.u8id = TLM_SLAVE_ID;
    frame.u8fct = 0x03;
    frame.u16RegAdd = 0x047D;
    frame.u16CoilsNo = REG047D_SIZE;
    frame.u16reg = reg047D;
    if (ModbusQueryPush(modH, frame))
        return true;
    else
        return false;
}